/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.hannesdorfmann.mosby3.mvi;

import com.hannesdorfmann.mosby3.AbilitySliceMviDelegate;
import com.hannesdorfmann.mosby3.AbilitySliceMviDelegateImpl;
import com.hannesdorfmann.mosby3.MviDelegateCallback;
import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
import com.hannesdorfmann.mosby3.mvp.MvpView;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;

/**
 * <p>
 * This abstract class can be used to extend from to implement an Model-View-Intent pattern with
 * this fragment as View and a {@link MviPresenter} to coordinate the View and the underlying
 * model (business logic)
 * </p>
 *
 * <p>
 * Per default {@link AbilitySliceMviDelegateImpl} is used with the following lifecycle:
 * The View is attached to the Presenter in {@link Fragment#onViewCreated(View, Bundle)}.
 * So you better instantiate all your UI widgets before that lifecycle callback (typically in
 * {@link
 * Fragment#onCreateView(LayoutInflater, ViewGroup, Bundle)}. The View is detached from Presenter in
 * {@link Fragment#onDestroyView()}
 * </p>
 *
 */
public abstract class MviAbilitySlice<V extends MvpView, P extends MviPresenter<V, ?>> extends AbilitySlice
    implements MvpView, MviDelegateCallback<V, P> {

  private boolean isRestoringViewState = false;
  protected AbilitySliceMviDelegate<V, P> mvpDelegate;

  @Override
  protected void onStart(Intent intent) {
    super.onStart(intent);
    getMvpDelegate().onStart(intent);
  }

  @Override
  protected void onStop() {
    super.onStop();
    getMvpDelegate().onStop();
  }

  @Override
  protected void onActive() {
    super.onActive();
    getMvpDelegate().onActive();
  }

  @Override
  protected void onInactive() {
    super.onInactive();
    getMvpDelegate().onInactive();
  }

  @Override
  protected void onForeground(Intent intent) {
    super.onForeground(intent);
    getMvpDelegate().onForeground(intent);
  }

  @Override
  protected void onBackground() {
    super.onBackground();
    getMvpDelegate().onBackground();
  }



  /**
   * Instantiate a presenter instance
   *
   * @return The {@link MvpPresenter} for this viewState
   */
  public abstract P createPresenter();

  /**
   * Get the mvp delegate. This is internally used for creating presenter, attaching and detaching
   * viewState from presenter.
   *
   * <p><b>Please note that only one instance of mvp delegate should be used per Fragment
   * instance</b>.
   * </p>
   *
   * <p>
   * Only override this method if you really know what you are doing.
   * </p>
   *
   * @return {@link AbilitySliceMviDelegate}
   */
  public AbilitySliceMviDelegate<V, P> getMvpDelegate() {
    if (mvpDelegate == null) {
      mvpDelegate = new AbilitySliceMviDelegateImpl<V, P>(this, this);
    }

    return mvpDelegate;
  }

  @Override public V getMvpView() {
    try {
      return (V) this;
    } catch (ClassCastException e) {
      String msg =
              "Couldn't cast the View to the corresponding View interface. Most likely you forgot to add \"Fragment implements YourMvpViewInterface\".\"";
      throw new RuntimeException(msg, e);
    }
  }

  @Override public void setRestoringViewState(boolean restoringViewState) {
    this.isRestoringViewState = restoringViewState;
  }

  protected boolean isRestoringViewState() {
    return isRestoringViewState;
  }


}
